Serverless FrameworkでAWS Lambdaファンクションをデプロイする(Rust版)
AWS LambdaのCustom Runtimesにより、様々な言語でLambdaファンクションを実装できるようになりました。個人的にはRustを使っていきたいと思っています(趣味です)。
RustでLambdaファンクションを実装するにあたり、Lambdaファンクションのデプロイの仕組みを整えておきたいところ。私の普段使いのデプロイツールはapexなのですが、apexは現時点でCustom Runtimesのデプロイには対応していません。このため、別のやり方としてServerless Frameworkを試してみました。
今回のエントリーではServerless Frameworkを使ってRustのLambdaファンクションをデプロイする方法をご紹介します。
目次
- 検証環境
- 前提
- 新規プロジェクト(Rustのパッケージ)作成
- Serverless FrameworkとRustプラグインのインストール
- Lambdaファンクションの作成
- Rustプログラムのコンパイル
- Serverless Frameworkの設定(serverless.yml)
- AWSのクレデンシャル
- Lambdaファンクションのデプロイ
- Lambdaファンクションの実行
- まとめ
検証環境
- macOS:Mojave(v10.14.2)
- Rust:v1.31.0
- Node.js:v11.6.0
- npm:v6.5.0
- AWS CLI:v1.16.80
- Serverless Framework :v1.35.1
- Docker Desktop Community:v2.0.0.0-mac81 DockerはRustプログラムのコンパイルで使用します。
前提
Serverless FrameworkのRustプラグインが公開されているのでこれを利用します。
テンプレートもいくつか用意されています。
今回はこれらのテンプレートを参考に、一から必要な設定ファイル等を作成していきます。
Lambdaファンクションは、DynamoDBからGetItemでデータを取得するサンプルプログラムを用意します。サンプルデータは以下のAWS公式ドキュメントのチュートリアルに付属のもの(moviedata.json)を利用します(※本ブログ記事ではDynamoDBのテーブル作成とデータロードについては触れません。必要に応じてチュートリアルの手順を参考にテーブル作成&データをロードしてください)。
新規プロジェクト(Rustのパッケージ)作成
はじめにcargo new
で新規のRustプロジェクト(Rustのパッケージ)を作成します。
cargo new dynamodb-getitem-sample --bin
Cargo.toml
とmain.rs
が作成されます。
. ├── Cargo.toml └── src └── main.rs
Serverless FrameworkとRustプラグインのインストール
プロジェクトディレクトリに、以下のようにpackage.json
を作成します。
{ "devDependencies": { "serverless": "1.35.1", "serverless-rust": "0.2.0" } }
npm install
でserverless
とserverless-rust
をインストールします。
$ npm install
この時点でディレクトリ構成は以下のようになります。
. ├── Cargo.toml ├── node_modules ├── package-lock.json ├── package.json └── src └── main.rs
Lambdaファンクションの作成
DynamoDBからGetItemでデータを取得するサンプルプログラムです。Rust用のAWS SDK(非公式)であるrusotoを使ってDynamoDBにアクセスします。
Cargo.toml
は以下のように設定します。Custom Runtimesを使用する場合、バイナリをbootstrap
という名前にする必要がありますが、このあたりはServerless FrameworkのRustプラグインがよしなにやってくれるため、Cargo.toml
でバイナリ名を明示的に指定する必要はありません。
[package] name = "dynamodb-getitem-sample" version = "0.1.0" authors = ["Yutaka Yawata"] edition = "2018" [dependencies] lambda_runtime = "0.1" log = "0.4.6" env_logger = "0.6.0" rusoto_core = "0.36.0" rusoto_dynamodb = "0.36.0" serde = "1.0.84" serde_derive = "1.0.84" serde_json = "1.0.34" serde_dynamodb = { git = "https://github.com/mockersf/serde_dynamodb.git", rev = "79e3dd7765574dce64a283a3ffb32f45079100b4" }
Rustプログラムのコンパイル
今回利用するServerless FrameworkのRustプラグインでは、Dockerを使ってRustプログラムをコンパイルする作りになっています。このため、手元のMac上ではクロスコンパイルの環境を整える必要はありません。
ちなみにこのDockerイメージはlambci/docker-lambdatをベースにしています。
Serverless Frameworkの設定(serverless.yml)
新規にserverless.yml
を作成し、以下のように設定します。シンプルに1つのLambdaファンクションをデプロイする設定です。Lambdaファンクションに割り当てるIAMロールには、DynamoDBのGetItem権限を追加します。
service: serverlss-rust-sample provider: name: aws runtime: rust memorySize: 128 region: ap-northeast-1 iamRoleStatements: - Effect: "Allow" Action: - "dynamodb:GetItem" Resource: - "arn:aws:dynamodb:ap-northeast-1:*:table/Movies" package: individually: true plugins: - serverless-rust functions: dynamodb-getitem-sample: handler: dynamodb-getitem-sample
runtime
にはrust
を、plugins
にserverless-rust
を指定します。functions
とhandler
には、いずれもRustのパッケージ名(ここではdynamodb-getitem-sample)を指定します。
AWSのクレデンシャル
以下を参考に設定します。基本的にはAWS CLIのそれと同じものが使えますので、Serverless Framework用の特別な設定は不要です。
Lambdaファンクションのデプロイ
serverless deploy
を実行すると、Rustプログラムのコンパイル 〜 Lambdaファンクションのデプロイが実行されます。
$ AWS_PROFILE=development npx serverless deploy --conceal Serverless: Building native Rust dynamodb-getitem-sample func... Finished release [optimized] target(s) in 4.87s adding: bootstrap (deflated 61%) Serverless: Packaging service... Serverless: Creating Stack... Serverless: Checking Stack create progress... ..... Serverless: Stack create finished... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service .zip file to S3 (2.34 MB)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... ............... Serverless: Stack update finished... Service Information service: serverless-rust-sample stage: dev region: ap-northeast-1 stack: serverless-rust-sample-dev api keys: None endpoints: None functions: dynamodb-getitem-sample: serverless-rust-sample-dev-dynamodb-getitem-sample layers: None
Lambdaファンクションの実行
serverless invoke
でLambdaファンクションを実行してみます。
$ AWS_PROFILE=development npx serverless invoke -f dynamodb-getitem-sample { "year": 2013, "title": "Rush", "info": { "plot": "A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.", "rating": 8.3 } }
まとめ
Serverless FrameworkとそのRustプラグインを利用することで、シングルコマンドでRustプログラムのコンパイル 〜 Lambdaファンクションのデプロイまでを実行することができます。とても便利ですね。これからRust on AWS Lambdaをいろいろ試していきたいと思います。